using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using QFramework;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;

public class DeckManager : MonoBehaviour, IController
{
    [SerializeField] GameObject cardPerfab;
    [SerializeField] GameObject smallCardPerfab;
    [SerializeField] GameObject deckPool;
    [SerializeField] GameObject wareHousePool;
    [SerializeField] TMP_Dropdown deckDropdown;

    /// <summary>
    /// 当前卡组的卡牌集合
    /// <卡牌ID，卡牌GameObject>
    /// </summary>
    private Dictionary<int, GameObject> currentDeckGameObjects;

    private XMLManager xmlManager;

    public CardData CardDataInfos { get; set; }

    public static DeckManager Instance { get; private set; }

    public IArchitecture GetArchitecture()
    {
        return CardGame.Interface;
    }

    void Awake()
    {
        Instance = this;
        currentDeckGameObjects = new Dictionary<int, GameObject>();
    }

    void Start()
    {
        this.xmlManager = gameObject.AddComponent<XMLManager>();
        this.xmlManager.Initialize("Data/DeckData.xml");
        if (!this.xmlManager.FileExists())
        {
            /* 
                文件Mac路径：/Users/yukilonger/Library/Application Support/DefaultCompany/Card/Data/DeckData.xml
                使用Application.persistentDataPath，路径取决于操作系统
            */
            this.xmlManager.CreateNewXML("Data");
            this.xmlManager.AddNode("/Data", "Deck", new Dictionary<string, string> { { "name", "卡组一" } });
            this.xmlManager.AddNode("/Data", "Deck", new Dictionary<string, string> { { "name", "卡组二" } });
        }
        XmlNodeList decks = this.xmlManager.QueryNodes("/Data/Deck");
        foreach (XmlNode deck in decks)
        {
            this.deckDropdown.options.Add(new TMP_Dropdown.OptionData(deck.Attributes["name"].Value));
        }
        this.deckDropdown.onValueChanged.AddListener(this.OnDeckDropdownValueChanged);

        this.CardDataInfos = this.GetModel<CardData>();
        LoadWareHouseCard();

        // 监听Canvas的渲染完成事件
        StartCoroutine(WaitForCanvasReady());
    }

    IEnumerator WaitForCanvasReady()
    {
        Canvas canvas = GetComponentInParent<Canvas>();
        if (canvas != null)
        {
            // 等待Canvas渲染
            yield return new WaitUntil(() => canvas.isActiveAndEnabled);
        }

        // 额外等待一帧确保UI组件创建完成
        yield return null;

        // Dropdown需要界面加载完成才能访问
        OnDeckDropdownValueChanged(0);
    }

    private void OnDeckDropdownValueChanged(int arg0)
    {
        this.deckPool.DestroyChildren();
        this.currentDeckGameObjects.Clear();

        var name = this.deckDropdown.captionText.text;
        var nodes = this.xmlManager.QueryNodes($"/Data/Deck[@name='{name}']/Card");
        foreach (XmlNode node in nodes)
        {
            var id = int.Parse(node.Attributes["id"].Value);
            var count = int.Parse(node.Attributes["count"].Value);
            var tempGameObject = CreateCard(id, count, this.smallCardPerfab, this.deckPool, true);
            this.currentDeckGameObjects.Add(id, tempGameObject);
        }
    }

    private void LoadWareHouseCard()
    {
        foreach (var card in this.CardDataInfos.ObtainedCards)
        {
            CreateCard(card.Key, card.Value, this.cardPerfab, this.wareHousePool);
        }
    }

    /// <summary>
    /// 创建卡牌
    /// </summary>
    /// <param name="id">卡牌ID</param>
    /// <param name="count">卡牌数量</param>
    /// <param name="perfab">卡牌预制体</param>
    /// <param name="pool">所属容器</param>
    /// <param name="isDeckCard">是否在卡组中</param>
    private GameObject CreateCard(int id, int count, GameObject perfab, GameObject pool, bool isDeckCard = false)
    {
        var cardInfo = this.CardDataInfos.Cards.FirstOrDefault(x => x.Id == id);
        
        if (cardInfo != null)
        {
            var tempCardInfo = DeepCopy.DeepCopyByExpressionTree(cardInfo);
            tempCardInfo.Count = count;
            var cardGameObject = Instantiate(perfab, pool.transform);
            cardGameObject.GetComponent<CardDisplay>().Card = tempCardInfo;

            if (isDeckCard)
            {
                cardGameObject.GetComponent<CardManager>().InDeckPool = true;
            }

            return cardGameObject;
        }

        return null;
    }

    #region 点击卡牌
    public void SendWareHouseToDeck(GameObject card)
    {
        var cardInfo = card.GetComponent<CardDisplay>().Card;
        int count = cardInfo.Count;
        if (count == 0)
            // 仓库中没卡牌了
            return;

        int id = cardInfo.Id;

        /* 卡组 */

        int deckCardCount = 1;
        var deckName = this.deckDropdown.captionText.text;

        if (this.currentDeckGameObjects.ContainsKey(id))
        {
            // 修改界面
            var cardDisplayComponent = this.currentDeckGameObjects[id].GetComponent<CardDisplay>();
            deckCardCount = cardDisplayComponent.Card.Count + 1;
            cardDisplayComponent.Card.Count = deckCardCount;
            cardDisplayComponent.textCount.text = deckCardCount.ToString();
            // 修改数据源
            this.xmlManager.UpdateNodeAttribute($"/Data/Deck[@name='{deckName}']/Card[@id='{id}']", "count", deckCardCount.ToString());
        }
        else
        {
            // 修改界面
            var tempGameObject = CreateCard(id, deckCardCount, this.smallCardPerfab, this.deckPool, true);
            // 修改数据源
            this.currentDeckGameObjects.Add(id, tempGameObject);
            this.xmlManager.AddNode($"/Data/Deck[@name='{deckName}']", "Card", new Dictionary<string, string> { { "id", id.ToString() }, { "count", deckCardCount.ToString() } });
        }

        /* 卡牌仓库 */
        
        cardInfo.Count--;
        card.GetComponent<CardDisplay>().textCount.text = cardInfo.Count.ToString();
        this.CardDataInfos.ObtainedCards[id] = cardInfo.Count; 
        this.CardDataInfos.SaveObtainedCards();
    }

    public void SendDeckToWareHouse(GameObject card)
    {
        var cardInfo = card.GetComponent<CardDisplay>().Card;
        int id = cardInfo.Id;
        int count = cardInfo.Count;
    }
    #endregion
}
